def repeat(cursor, func):
    res = []
    while True:
        v = func(cursor)
        if v is not None:
            res.append(v)
        if not cursor.goto_next_sibling():
            break
    cursor.goto_parent()
    return res

def eval_node(cursor):
    if cursor.node.type == "file":
        cursor.goto_first_child()
        vals = repeat(cursor, eval_stmt)
        if len(vals) > 0:
            return vals[-1]
        return None
    else:
        return None
    
def eval_stmt(cursor):
    return eval_expr(cursor)
    # if not cursor.goto_first_child():
        # return None

def eval_expr(cursor):
    res = None
    if cursor.node.type == "binary":
        res = eval_binary(cursor)
    else:
        res = eval_primary(cursor)
    return res

def eval_primary(cursor):
    if cursor.node.type == "group":
        if not cursor.goto_first_child():
            return None
        if not cursor.goto_next_sibling(): # skip (
            return None
        res = eval_expr(cursor)
        cursor.goto_parent()
    elif cursor.node.type == "integer":
        res = eval_int(cursor)
    elif cursor.node.type == "float":
        res = eval_float(cursor)
    elif cursor.node.type == "string":
        res = eval_string(cursor)
    elif cursor.node.type == "bool":
        res = eval_bool(cursor)
    else:
        print("error:", cursor.node.type)
    return res

def eval_binary(cursor):
    cursor.goto_first_child()
    left = eval_expr(cursor)
    cursor.goto_next_sibling()
    op = str(cursor.node.text, encoding='utf-8')
    cursor.goto_next_sibling()
    right = eval_expr(cursor)
    res = None
    if op == "+":
        res = left + right
    elif op == "-":
        res = left - right
    elif op == "*":
        res = left * right
    elif op == "/":
        res = left / right
    cursor.goto_parent()
    return res

def eval_int(cursor):
    return int(cursor.node.text)

def eval_float(cursor):
    return float(cursor.node.text)

def eval_string(cursor):
    return str(cursor.node.text[1:-1], encoding='utf-8')

def eval_bool(cursor):
    t = str(cursor.node.text, encoding='utf-8')
    if t == "true":
        return True
    else:
        return False

def interp(tree):
    root = tree.root_node
    cursor = tree.walk()
    val = eval_node(cursor)
    return val
